﻿using Gurux.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Gds.Utility.Helper
{
    public class SerialHelper
    {
        readonly Gurux.Serial.GXSerial Cl = new Gurux.Serial.GXSerial();

        public event EventHandler ShowLogEvent;
        public int ControllerIndex = 0;
        public int TotalLineIndex = 0;
        public string AnalyzeType = "";
        public string meterNumber = "";
        public string ReceivedText = "";
        public string Port { get; set; }
        public bool IsOpen { get { return Cl.IsOpen; } }
        public string Baudrate { get; set; }
        public int WaitTime = 200;
        public int ByteWaitTime = 0;
        public void OpenPort()
        {
            Cl.Close();
            try
            {
                if (Cl.IsOpen == false)
                {
                    //Cl.Settings = GXSerialSample.Properties.Settings.Default.MediaSetting;
                    Cl.Trace = TraceLevel.Verbose;
                    string[] arrybaudRate = Baudrate.Split(',');
                    Cl.PortName = Port;
                    Cl.BaudRate = int.Parse(arrybaudRate[0]);
                    Cl.DataBits = int.Parse(arrybaudRate[2]);
                    if (arrybaudRate[1] == "e")
                    {
                        Cl.Parity = System.IO.Ports.Parity.Even;
                    }
                    else
                    {
                        Cl.Parity = System.IO.Ports.Parity.None;
                    }
                    Cl.StopBits = System.IO.Ports.StopBits.One;
                    Cl.OnReceived -= new ReceivedEventHandler(this.OnReceived);
                    Cl.OnReceived += new ReceivedEventHandler(this.OnReceived);

                    Cl.OnError -= new ErrorEventHandler(this.gxSerial1_OnError);
                    Cl.OnError += new ErrorEventHandler(this.gxSerial1_OnError);
                    Cl.OnTrace += Cl_OnTrace;
                    //Cl.OnMediaStateChange += new MediaStateChangeEventHandler(gxSerial1_OnMediaStateChange);
                    Cl.DtrEnable = Cl.RtsEnable = true;
                    Cl.Open();
                }
            }
            catch (Exception ex)
            {
                PublicHelper.WriteErrorMsg(ex.Message);
            }
        }

        private void Cl_OnTrace(object sender, TraceEventArgs e)
        {
            if ((e.Type & TraceTypes.Info) != 0)
            {
                System.Diagnostics.Debug.WriteLine(e.ToString());
            }
            else if ((e.Type & TraceTypes.Error) != 0)
            {
                System.Diagnostics.Debug.WriteLine(e.ToString());
            }
            else if ((e.Type & TraceTypes.Warning) != 0)
            {
                System.Diagnostics.Debug.WriteLine(e.ToString());
            }
            else if ((e.Type & TraceTypes.Sent) != 0)
            {
                System.Diagnostics.Debug.WriteLine("<- " + e.ToString());
            }
            else if ((e.Type & TraceTypes.Received) != 0)
            {
                System.Diagnostics.Debug.WriteLine("-> " + e.ToString());
            }
        }

        public void ClosePort()
        {
            try
            {
                if (Cl.IsOpen == true)
                {
                    Cl.Close();
                    Cl.Dispose();
                }
            }
            catch (Exception Ex)
            {
                //PublicHelper.WriteErrorMsg(Ex.Message);
            }
        }

        private void OnReceived(object sender, ReceiveEventArgs e)
        {
            try
            {
                // Byte array received from GXSerial, and must be changed to chars.
                if (ControllerIndex == 1)
                {
                    //ShowLogEvent("["+DateTime.Now.ToString("mm:ss.fff")+"][Receive]"+GXCommon.ToHex((byte[])e.Data),new EventArgs ());
                }
                if (AnalyzeType == "Hex")
                {
                    //System.Threading.Thread.Sleep(500);
                    ReceivedText += GXCommon.ToHex((byte[])e.Data);
                    //Console.WriteLine("R:"+ReceivedText);
                }
                else
                {
                    ReceivedText += System.Text.Encoding.ASCII.GetString((byte[])e.Data);
                }
                // Helper.PublicHelper.WriteLogMsg(ReceivedText, meterNumber, "收");
            }
            catch (Exception Ex)
            {
                PublicHelper.WriteErrorMsg(Ex.Message);
            }
        }
        public bool SendData(string code)
        {
            bool result = true;
            try
            {
                lock (Cl)
                {
                    Cl.ResetByteCounters();
                    if (Cl.RtsEnable)
                    {
                        ReceivedText = "";
                        if (Cl.IsOpen == false)
                        {
                            //判断当前是否还存在这个端口
                            bool isContainSerialPort = false;
                            var portsList = System.IO.Ports.SerialPort.GetPortNames();
                            foreach (var port in portsList)
                            {
                                if (port == Port)
                                {
                                    isContainSerialPort = true;
                                    break;
                                }
                            }
                            if (isContainSerialPort)
                            {
                                Cl.Open();
                            }

                            return false;
                        }
                        //Cl.RtsEnable = true;
                        //System.Threading.Thread.Sleep(800);
                        if (AnalyzeType == "Hex")
                        {
                            Cl.Send(GXCommon.HexToBytes(code));
                            if (ControllerIndex == 1)
                            {
                                //ShowLogEvent("[" + DateTime.Now.ToString("mm:ss.fff") + "][Send]" + code, new EventArgs());
                            }
                        }
                        else
                        {
                            Cl.Send(code);

                        }


                        Console.WriteLine("S:" + code);
                    }
                    else
                    {
                        Console.WriteLine("task can not send");
                    }
                }


            }
            catch (Exception ex)
            {
                Helper.PublicHelper.WriteErrorMsg("[" + Cl.PortName + "]" + Cl.ToString() + ex);
                Process myProcess = Process.GetCurrentProcess();//获取该进程
                                                                //ProcessThreadCollection PTC = myProcess.Threads;//获取其关联的线程，包括主线程    
                                                                //int num = PTC.Count;//获取线程数量
                PerformanceCounter pf1 = new PerformanceCounter("Process", "Working Set - Private", myProcess.ProcessName);
                PerformanceCounter pf2 = new PerformanceCounter("Process", "Working Set", myProcess.ProcessName);
                Helper.PublicHelper.WriteErrorMsg(string.Format("{0}:{1}{2:N}Kb", myProcess.ProcessName, "process", myProcess.WorkingSet64 / 1024));
                Helper.PublicHelper.WriteErrorMsg(string.Format("{0}:{1}{2:N}Kb", myProcess.ProcessName, "process Col", pf2.NextValue() / 1024));
                Helper.PublicHelper.WriteErrorMsg(string.Format("{0}:{1}{2:N}Kb", myProcess.ProcessName, "process private", pf1.NextValue() / 1024));
                result = false;
            }
            return result;
            // PublicHelper.WriteLogMsg(code, meterNumber, "发");
        }

        public bool SendData(System.IO.Ports.SerialPort _port, string code)
        {
            bool result = true;
            try
            {
                _port.Write(GXCommon.HexToBytes(code), 0, GXCommon.HexToBytes(code).Length);
            }
            catch (Exception ex)
            {
                Helper.PublicHelper.WriteErrorMsg(ex);
                result = false;
            }
            return result;
            // PublicHelper.WriteLogMsg(code, meterNumber, "发");
        }

        public void SetRtsEnable(bool setFlag)
        {
            Cl.RtsEnable = setFlag;
        }
        public void SendData(string code, bool hexFlag)
        {
            ReceivedText = "";
            Cl.Send(GXCommon.HexToBytes(code));
            Console.WriteLine("S:" + code);
            //ViewModel.ViewModel.MainViewModel.Instance.SendData = "SendD:(" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ")" + code;
            // PublicHelper.WriteLogMsg(code, meterNumber, "发");
        }
        public void SendData(byte[] code, bool hexFlag)
        {
            ReceivedText = "";
            Cl.Send(code);
            Console.WriteLine(ByteArrayToHexString(code));
            //ViewModel.ViewModel.MainViewModel.Instance.SendData = "SendD:(" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ")" + ByteArrayToHexString(code);

            // PublicHelper.WriteLogMsg(code, meterNumber, "发");
        }
        public void SendDataSynchronous(string code, out string reply)
        {
            try
            {
                reply = "";
                Cl.OnReceived -= new ReceivedEventHandler(this.OnReceived);
                lock (Cl.Synchronous)
                {
                    Gurux.Common.ReceiveParameters<byte[]> p = new Gurux.Common.ReceiveParameters<byte[]>()
                    {
                        WaitTime = Convert.ToInt32(1000),
                        Eop = '\r',
                    };
                    Cl.Send(code);
                    Cl.Send('\r');

                    // PublicHelper.WriteLogMsg(code, meterNumber, "发");

                    if (Cl.Receive(p))
                    {
                        // p.Reply;  返回
                        reply = Convert.ToString(p.Reply);
                        // PublicHelper.WriteLogMsg(reply, meterNumber, "收");
                    }
                }
            }
            catch (Exception Ex)
            {
                reply = "";
                // PublicHelper.WriteErrorMsg(Ex.Message);
            }
        }
        private void gxSerial1_OnError(object sender, Exception ex)
        {
            try
            {
                Cl.Close();
                // PublicHelper.WriteErrorMsg(ex.Message);

            }
            catch (Exception Ex)
            {
                PublicHelper.WriteErrorMsg(Ex, "串口关闭");
            }
        }
        public string ByteArrayToHexString(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (var k in data)
            {
                sb.Append(Convert.ToString(k, 16).PadLeft(2, '0'));
            }
            return sb.ToString().ToUpper();
        }

        public bool GetSerialPortStatus()
        {
            return Cl.IsOpen;
        }
    }
}
